#include "filesystemaction.h"
#include <QDebug>
#include <QTimer>

#define  STEP_FILES               5
#define  COPY_BUFFER_SIZE         4096

FileSystemAction::FileSystemAction(QObject *parent) : QObject(parent)
{

}

FileSystemAction::~FileSystemAction()
{
    fileclose();
}

void FileSystemAction::startCopy(QString source, QString target)
{
    QFileInfo sourceInfo(source);
    m_sourceSize = quint64(sourceInfo.size());

    m_sourceFile.setFileName(source);
    bool ret = m_sourceFile.open(QIODevice::ReadOnly);
    if(!ret) {
        qDebug() << source << "open failed";
        return;
    }

    m_targetFile.setFileName(target);
    ret = m_targetFile.open(QIODevice::WriteOnly | QIODevice::Truncate);
    if(!ret) {
        qDebug() << target << "open failed";
        return;
    }

    m_bytesWritten = 0;
    m_cancelCurrentAction = false;

    processCopySingleFile();
}

void FileSystemAction::cancelCopy()
{
    m_cancelCurrentAction = true;
}

void FileSystemAction::fileclose()
{
    if (m_sourceFile.isOpen()) {
        m_sourceFile.close();
    }
    if (m_targetFile.isOpen()) {
        m_targetFile.close();
    }
}

int FileSystemAction::getPercent()
{
    int percent = 0;

    if (m_sourceSize > 0) {
        percent = int(m_bytesWritten * 100 / m_sourceSize);
    }

    if (percent > 100) {
        percent = 100;
    }

    return percent;
}

bool FileSystemAction::processCopySingleFile()
{
    char block[COPY_BUFFER_SIZE];
    int  step = 0;
    bool copySingleFileDone = false;
    bool scheduleAnySlot    = true;
    quint64  startBytes     = m_bytesWritten;

    while (!m_sourceFile.atEnd()
               && !m_cancelCurrentAction
               && m_bytesWritten < m_sourceSize
               && step++ < STEP_FILES) {
        qint64 in = m_sourceFile.read(block, sizeof(block));
        if (in > 0) {
            if (in != m_targetFile.write(block, in)) {
                fileclose();
                m_cancelCurrentAction = true;
                break;
            }
            m_bytesWritten += quint64(in);
        }
    }

    if (!m_cancelCurrentAction
            && m_sourceFile.isOpen()
            && m_bytesWritten == m_sourceSize) {
        fileclose();
        copySingleFileDone = true;
    }

    if (m_cancelCurrentAction) {
        fileclose();
        m_targetFile.remove();
        int percent = getPercent();
        emit progress(m_sourceSize, m_bytesWritten, percent);
        qDebug() << "Oh, cancel copy " << "sourceSize:" << m_sourceSize << "bytesWritten:" << m_bytesWritten << "percent:" << percent;
    } else {
        if (copySingleFileDone) {
            if (startBytes > 0) {
                //the whole took more than one call to copySingleFile()
                int percent = getPercent();
                emit progress(m_sourceSize, m_bytesWritten, percent);
                qDebug() << "Yeah, copy done: " << "sourceSize:" << m_sourceSize << "bytesWritten:" << m_bytesWritten << "percent:" << percent;
            } else {
                //return normally to entry loop
                scheduleAnySlot = false;
            }
        } else {
            int percent = getPercent();
            emit progress(m_sourceSize, m_bytesWritten, percent);
            qDebug() << "cpoying :"<< "sourceSize:" << m_sourceSize << "bytesWritten:" << m_bytesWritten << "percent:" << percent;
            QTimer::singleShot(0, this, SLOT(processCopySingleFile()));
        }
    }

    return scheduleAnySlot;
}
